package question5.com.qee.jdbc;

import org.springframework.util.StringUtils;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;

public class TransactionJdbcSession extends ConnectionHolder implements TransactionSession {


    public static void main(String[] args) {
        Matcher matcher = columnNamePattern.matcher("insert into tb_user(id,name,feature,create_time,update_time) values(?,?,?,?,?)");
        boolean matches = matcher.find();
        System.out.println(matches);
        System.out.println(matcher.group());

    }

    @Override
    public Statement createStatement(String sql) {
        try {
            return connection.prepareStatement(sql);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }

    @Override
    public void beginTransaction() throws SQLException {
        connection.setAutoCommit(false);
    }

    @Override
    public void commitTransaction() throws SQLException {
        connection.commit();
    }

    @Override
    public void rollbackTransaction() throws SQLException {
        connection.rollback();
    }

    // select * from tb_user where id=? and xxx =xxx?
    @Override
    public <T> List<T> selectList(String sql, Map<String, Object> paramMap, Class<T> resultType) throws SQLException, IllegalAccessException, InstantiationException {
        try (PreparedStatement preparedStatement = (PreparedStatement) createStatement(sql)) {

            if (paramMap != null && paramMap.size() > 0) {
                Matcher matcher = pattern.matcher(sql);
                int idx = 1;
                while (matcher.find()) {
                    Object value = paramMap.get(matcher.group(1));
                    if (value instanceof String) {
                        preparedStatement.setString(idx++, (String) value);
                    } else if (value instanceof Integer) {
                        preparedStatement.setInt(idx++, (Integer) value);
                    } else if (value instanceof Long) {
                        preparedStatement.setLong(idx++, (Long) value);
                    } else if (value instanceof Date) {
                        preparedStatement.setDate(idx++, new java.sql.Date(((Date) value).getTime()));
                    }
                }
            }
            preparedStatement.execute();
            return getResult(resultType, preparedStatement.getResultSet());
        }
    }

    @Override
    public <T> T selectOne(String sql, Map<String, Object> paramMap, Class<T> resultType) throws IllegalAccessException, SQLException, InstantiationException {
        List<T> result = selectList(sql, paramMap, resultType);
        if (result == null) {
            return null;
        }
        return result.get(0);
    }

    @Override
    public int insert(String sql, Map<String, Object> paramMap) throws SQLException {
        List<Map<String, Object>> paramList = new ArrayList<>();
        paramList.add(paramMap);
        return batchInsert(sql, paramList);
    }

    // insert into tb_user(id,name,feature,create_time,update_time) values (?,?,?,?,?)
    @Override
    public int batchInsert(String sql, List<Map<String, Object>> paramList) throws SQLException {
        try (PreparedStatement preparedStatement = (PreparedStatement) createStatement(sql)) {
            Matcher matcher = columnNamePattern.matcher(sql);
            System.out.println(matcher.find());
            System.out.println(sql);
            String tableCln = null;
            try {
                tableCln = matcher.group();
            } catch (Exception e) {
                e.printStackTrace();
            }
            tableCln = tableCln.substring(1, tableCln.length() - 2);
            String[] colns = tableCln.split(",");
            for (Map<String, Object> paramMap : paramList) {
                int idx = 1;
                for (String cln : colns) {

                    Object value = paramMap.get(StringUtils.trimAllWhitespace(AbcUtils.lineToHump(cln)));
                    if (value instanceof String) {
                        preparedStatement.setString(idx++, (String) value);
                    } else if (value instanceof Integer) {
                        preparedStatement.setInt(idx++, (Integer) value);
                    } else if (value instanceof Long) {
                        preparedStatement.setLong(idx++, (Long) value);
                    } else if (value instanceof Date) {
                        preparedStatement.setDate(idx++, new java.sql.Date(((Date) value).getTime()));
                    }
                }
                preparedStatement.addBatch();
            }
            int[] ints = preparedStatement.executeBatch();
            return Arrays.stream(ints).sum();
        }
    }

    // update table set xx=? where sss=?
    @Override
    public int update(String sql, Map<String, Object> paramMap) throws SQLException {
        try (PreparedStatement preparedStatement = (PreparedStatement) createStatement(sql)) {
            Matcher matcher = pattern.matcher(sql);
            int idx = 1;
            if (paramMap != null && paramMap.size() > 0) {
                while (matcher.find()) {
                    Object value = paramMap.get(AbcUtils.lineToHump(matcher.group(1)));
                    if (value instanceof String) {
                        preparedStatement.setString(idx++, (String) value);
                    } else if (value instanceof Integer) {
                        preparedStatement.setInt(idx++, (Integer) value);
                    } else if (value instanceof Long) {
                        preparedStatement.setLong(idx++, (Long) value);
                    } else if (value instanceof Date) {
                        preparedStatement.setDate(idx++, new java.sql.Date(((Date) value).getTime()));
                    }
                }
            }
            preparedStatement.execute();
            return preparedStatement.getUpdateCount();
        }
    }
}
